package personal.zq.practice.common.utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonUtil {

    private JsonUtil() {
    }

    private volatile static Gson gson;

    public static Gson getGson() {
        return newInstance();
    }

    private static Gson newInstance() {
        if (gson != null) {
            return gson;
        }
        synchronized (JsonUtil.class) {
            if (gson == null) {
                gson = new Gson();
            }
        }
        return gson;
    }

    public static String toJson(Object obj) {
        return newInstance().toJson(obj);
    }

    /**
     * json字符串转换成bean
     *
     * @param json json字符串
     * @param clz  类
     * @return T
     */
    public static <T> T toBean(String json, Class<T> clz) {
        return newInstance().fromJson(json, clz);
    }

    /**
     * json字符串转换成Map
     *
     * @param json json字符串
     * @param clz  类
     * @return Map
     */
    public static <T> Map<String, T> toMap(String json, Class<T> clz) {
        Map<String, JsonObject> map = newInstance()
                .fromJson(json, new TypeToken<Map<String, JsonObject>>() {
                }.getType());
        Map<String, T> result = new HashMap<>(map.size());
        for (Map.Entry<String, JsonObject> entry : map.entrySet()) {
            result.put(entry.getKey(), newInstance().fromJson(entry.getValue(), clz));
        }
        return result;
    }


    /**
     * json字符串转换成List
     *
     * @param json json字符串
     * @param clz  类
     * @return List
     */
    public static <T> List<T> toList(String json, Class<T> clz) {
        JsonArray array = new JsonParser().parse(json).getAsJsonArray();
        List<T> list = new ArrayList<>();
        for (final JsonElement elem : array) {
            list.add(newInstance().fromJson(elem, clz));
        }
        return list;
    }

    /**
     * json字符串转换成List
     *
     * @param json json字符串
     * @return List
     */
    public static <T> List<Map<String, T>> toListMap(String json, Class<T> clazz) {
        JsonArray array = new JsonParser().parse(json).getAsJsonArray();
        List<Map<String, T>> list = new ArrayList<>();
        Type type = new TypeToken<HashMap<String, T>>() {
        }.getType();
        Gson g = new GsonBuilder()
                .registerTypeAdapter(new TypeToken<HashMap<String, Object>>() {
                        }.getType(),
                        (JsonDeserializer<HashMap<String, Object>>) (jsonElement, typeOfT, context) -> {
                            HashMap<String, Object> hashMap = new HashMap<>();
                            JsonObject jsonObject = jsonElement.getAsJsonObject();
                            for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
                                hashMap.put(entry.getKey(), entry.getValue());
                            }
                            return hashMap;
                        }).create();
        for (final JsonElement elem : array) {
            Map<String, T> map = g.fromJson(elem, type);
            list.add(map);
        }
        return list;
    }

}
